package btstack

/*
#include "btstack.h"

void PacketCallback(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
*/
import "C"
import (
	"bytes"
	"encoding/binary"
	"unsafe"
)

type HciEventHandlerType func(packet interface{})

var hciEventHandler HciEventHandlerType

func HciSetEventHandler(Callback HciEventHandlerType) {
	if hciEventHandler != nil {
		return
	}

	hciEventHandler = Callback

	var callbackHandler C.btstack_packet_callback_registration_t
	callbackHandler.callback = C.btstack_packet_handler_t(C.PacketCallback)
	C.hci_add_event_handler(&callbackHandler)
}

func handleNotification(packet []byte) {
	var handle uint16
	bytesBuffer := bytes.NewBuffer(packet[2:4])
	binary.Read(bytesBuffer, binary.LittleEndian, &handle)

	var valueHandle uint16
	bytesBuffer = bytes.NewBuffer(packet[4:6])
	binary.Read(bytesBuffer, binary.LittleEndian, &valueHandle)

	var valueLength uint16
	bytesBuffer = bytes.NewBuffer(packet[6:8])
	binary.Read(bytesBuffer, binary.LittleEndian, &valueLength)

	ValueUpdatesCallbacks[valueHandle](valueHandle, packet[8:8+valueLength])
}

//export PacketCallback
func PacketCallback(packetType C.uint8_t, ch C.uint16_t, packet *C.uint8_t, size C.uint16_t) {
	if hciEventHandler == nil {
		return
	}

	p := C.GoBytes(unsafe.Pointer(packet), C.int(size))
	var x interface{}

	switch packetType {
	case C.HCI_EVENT_PACKET:
		switch p[0] {
		case C.BTSTACK_EVENT_POWERON_FAILED:
			x = &EventPoweronFailedPacket{p}
		case C.BTSTACK_EVENT_STATE:
			x = &EventStatePacket{p}
		case C.GAP_EVENT_ADVERTISING_REPORT:
			x = parseAdvertisingReportPacket(&EventAdvertisingReportPacket{packet: p})
		case C.HCI_EVENT_LE_META:
			subeventCode := p[2]
			switch subeventCode {
			case C.HCI_SUBEVENT_LE_CONNECTION_COMPLETE:
				x = &EventLeConnectionCompletePacket{p}
			}
		case C.HCI_EVENT_DISCONNECTION_COMPLETE:
			x = &EventDisconnectionCompletePacket{p}
		case C.GATT_EVENT_SERVICE_QUERY_RESULT:
			x = &EventLeServiceQueryResultPacket{p}
		case C.GATT_EVENT_CHARACTERISTIC_QUERY_RESULT:
			x = &EventCharacteristicQueryResult{p}
		case C.GATT_EVENT_QUERY_COMPLETE:
			x = &EventQueryCompletePacket{p}
		case C.GATT_EVENT_NOTIFICATION:
			handleNotification(p)
		case C.GAP_EVENT_RSSI_MEASUREMENT:
			x = &EventRssiMeasurementPacket{p}
		}
	}

	if x == nil {
		return
	}

	hciEventHandler(x)
}

//export AttPacketHandler
func AttPacketHandler(packetType C.uint8_t, ch C.uint16_t, packet *C.uint8_t, size C.uint16_t) {

}
